package com.example.springbatchdemo.future;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Classname FutureInAction3
 * @Description TODO
 * @Date 2020/9/26 19:13
 * @Created by kevin
 */
public class FutureInAction3 {
    private static <T> Future<T> invoke( Callable<T> callable ) {

        AtomicReference<T> result = new AtomicReference<>();
        AtomicBoolean finished = new AtomicBoolean(false);

        Future<T> future = new Future<T>() {

            private Comparable<T> comparable;


            @Override
            public T get() {
                return result.get();
            }

            @Override
            public boolean isDone() {
                return finished.get();
            }

            @Override
            public void setCompletable( Comparable<T> completable ) {
                this.comparable = completable;
            }

            @Override
            public Comparable<T> getCompletable() {
                return comparable;
            }


        };

        Thread t = new Thread(() -> {
            try {
                T value = callable.action();
                result.set(value);
                finished.set(true);
                if (future.getCompletable() != null) {
                    future.getCompletable().complete(value);
                }
            } catch (Throwable cause) {
                if (future.getCompletable() != null) {
                    future.getCompletable().execption(cause);
                }
            }
        });

        t.start();


        return future;

    }

    private interface Future<T> {

        T get();

        boolean isDone();

        void setCompletable( Comparable<T> completable );

        Comparable<T> getCompletable();
    }

    private interface Callable<T> {
        T action();
    }

    private interface Comparable<T> {

        void complete( T t );

        void execption( Throwable cause );
    }
}
